package com.xcity.game.activity.oneyuan;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.security.SecureRandom;
import java.util.Collection;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import com.xcity.config.ConfigEx;
import com.xcity.db.entity.Config;
import com.xcity.db.entity.Player;
import com.xcity.db.mapper.ConfigMapper;
import com.xcity.game.activity.oneyuan.util.RobotUtils;
import com.xcity.util.DBUtils;

import naga.x.App;
import naga.x.util.IOUtils;
import naga.x.util.IOUtils.LineReaderListener;
import naga.x.util.StringUtils;

/**
 * 一元活动奖池
 * @author yang.li
 *
 */
public class OneYuanActivityPool {

	/** 活动期号 */
	protected int phase;
	/** 第几轮 */
	protected int round;
	/** 奖池当前累计金额 */
	protected int poolValue;
	/** 奖池最大金额 */
	protected int poolMax = DEFAULT_POOL_MAX;
	
	public static final int DEFAULT_POOL_MAX = 8888;
	
	// 参与纪录
	protected Map<Long, OneYuanActivityRecord> recordsMap = new ConcurrentHashMap<Long, OneYuanActivityRecord>();
	protected long[] recordIds;
	protected int recordIndex;
	protected static final Random RND = new SecureRandom();
	protected static final Logger LOG = OneYuanBigPrizeActivityService.LOG;
	
	public OneYuanActivityPool() {
	}
	
	public OneYuanActivityPool(int phase) {
		this.phase = phase;
		this.round = 1;
		this.recordIds = new long[poolMax];
	}

	public int getPhase() {
		return phase;
	}

	public void setPhase(int phase) {
		this.phase = phase;
	}

	public int getRound() {
		return round;
	}

	public void setRound(int round) {
		this.round = round;
	}

	public int getPoolValue() {
		return poolValue;
	}

	public void setPoolValue(int poolValue) {
		this.poolValue = poolValue;
	}

	public int getPoolMax() {
		return poolMax;
	}

	public void setPoolMax(int poolMax) {
		this.poolMax = poolMax;
	}
	
	public void nextRound() {
		phase = App.getApp().getServiceManager().get(OneYuanBigPrizeActivityService.class).getNowPhase();
		round++;
		poolValue = 0;
		recordsMap.clear();
		recordIds = new long[poolMax];
		recordIndex = 0;
		LOG.info("[1YUAN NEXT ROUND]PHASE[{}]ROUND[{}]POOL[{}]MAX[{}]", getPhase(), getRound(), getPoolValue(), getPoolMax());
	}
	
	/**
	 * 累加奖池
	 * @param val 剩余未加进奖池的值
	 * @return
	 */
	public int addValue(int val) {
		if (val <= 0) {
			return 0;
		}
		val += poolValue;
		int overflow = val - poolMax;
		if (overflow > 0) {
			poolValue = poolMax;
			return overflow;
		}
		poolValue = val;
		return 0;
	}
	
	protected File getSerializeFile() {
//		return new File(App.getApp().getConfig().getString(naga.x.common.Config.DATA_DIR), "db/1yuan." + phase + "." + round + ".txt");
//		return new File(App.getApp().getConfig().dataDir, "db/1yuan." + phase + "." + round + ".txt");
		ConfigEx config = App.getApp().getConfig();
		return new File(config.localDbDir, "1yuan." + phase + "." + round + ".txt");
	}
	
	@JSONField(serialize = false)
	public boolean isEnd() {
		return poolValue >= poolMax;
	}
	
	public OneYuanActivityRecord getRecord(long playerId) {
		return recordsMap.get(playerId);
	}
	
	public int addRecord(Player player, int money) {
		Long playerId = Long.valueOf(player.getId());
		int overflow = addValue(money);
		OneYuanActivityRecord record = recordsMap.get(playerId);
		if (record == null) {
			record = new OneYuanActivityRecord(player);
			recordsMap.put(playerId, record);
		}
		record.addNumber(money -= overflow);
		if (recordIds == null) {
			recordIds = new long[poolMax];
		}
		for (int i = 0; i < money; i++) {
			recordIds[recordIndex++] = playerId;
		}
		LOG.info("[1YUAN]ID[{}]VAL[{}]PHASE[{}]ROUND[{}]POOL[{}]POOLMAX[{}]", playerId, record.getNumber(), getPhase(), getRound(), getPoolValue(), getPoolMax());
		return overflow;
	}
	
	/**
	 * 抽奖
	 * @return 返回中奖玩家id
	 */
	protected long drawLottery() {
		return RobotUtils.getFakePrizePlayer();
//		int index = RND.nextInt(poolMax);
//		return recordIds[index];
	}
	
	protected void load() {
		if (recordIds == null) {
			recordIds = new long[poolMax];
		}
		File file = getSerializeFile();
		IOUtils.read(file, IOUtils.UTF8, new LineReaderListener() {
			@Override
			public boolean readLine(String line) {
				OneYuanActivityRecord record = OneYuanActivityRecord.deserialize(StringUtils.trim(line));
				recordsMap.put(record.getId(), record);
				for (int i = 0; i < record.getNumber(); i++) {
					recordIds[recordIndex++] = record.getId();
				}
				return true;
			}
		});
	}
	
	protected void save() {
		// 存储活动信息
		try {
			DBUtils.update(new Config(Config.KEY_ONE_YUAN_ACTIVITY, JSON.toJSONString(this)), ConfigMapper.class);
		} catch (Exception e) {
			LOG.error("[1YUAN SAVE ERRRO]PHASE[" + getPhase() + "]ROUND[" + getRound() + "]", e);
		}
		// 存储玩家参与纪录
		File file = getSerializeFile();
		IOUtils.createNewFile(file);
		BufferedWriter writer = null;
		try {
			writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), IOUtils.UTF8), 102400);
			Collection<OneYuanActivityRecord> vals = recordsMap.values();
			boolean newline = false;
			for (OneYuanActivityRecord val : vals) {
				if (newline) {
					writer.write(System.lineSeparator());
				}
				writer.write(val.toString());
				newline = true;
			}
			IOUtils.flushQuietly(writer);
		} catch (Exception e) {
			LOG.error("[1YUAN SAVE ERRRO]PHASE[" + getPhase() + "]ROUND[" + getRound() + "]", e);
		} finally {
			IOUtils.closeQuietly(writer);
		}
	}
	
}
